//
// Created by ZLY on 2025/3/29.
//

#include "DecodeThread.h"


DecodeThread::DecodeThread(AVPacketQueue *packet_queue, AVFrameQueue *frame_queue)
    : packet_queue_(packet_queue), frame_queue_(frame_queue) {
}

DecodeThread::~DecodeThread() {
    if (thread_) {
        Stop();
    }
    if (codec_ctx_) {
        avcodec_free_context(&codec_ctx_);
    }
}

int DecodeThread::Init(AVCodecParameters *par) {
    if (!par) {
        av_log(NULL, AV_LOG_ERROR, "par is null\n");
        return -1;
    }
    codec_ctx_ = avcodec_alloc_context3(NULL);
    int ret = avcodec_parameters_to_context(codec_ctx_, par);
    if (ret < 0) {
        av_strerror(ret, err2str, sizeof(err2str));
        av_log(NULL, AV_LOG_ERROR, "Failed to copy codec parameters: %s\n", err2str);
        return -1;
    }
    const AVCodec *codec = avcodec_find_decoder(codec_ctx_->codec_id);

    ret = avcodec_open2(codec_ctx_, codec, nullptr);
    if (ret < 0) {
        av_strerror(ret, err2str, sizeof(err2str));
        av_log(NULL, AV_LOG_ERROR, "Could not open codec\n");
        return -1;
    }
    av_log(NULL,AV_LOG_INFO, "init finish\n");
    return 0;
}

int DecodeThread::Start() {
    thread_ = new std::thread(&DecodeThread::Run, this);
    if (!thread_) {
        av_log(NULL, AV_LOG_ERROR, "DecodeThread::Start() ERROR\n");
        return -1;
    }
    return 0;
}

int DecodeThread::Stop() {
    return Thread::Stop();
}

void DecodeThread::Run() {
    AVFrame *frame = av_frame_alloc();
    av_log(NULL, AV_LOG_INFO, "DecodeThread::Start()\n");
    while (abort_ != 1) {
        //消费数据帧
        if (packet_queue_->Size()<10) {
            av_log(NULL, AV_LOG_VERBOSE, "DecodeThread::Stop() sleep\n");
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
            continue;
        }
        AVPacket *packet = packet_queue_->Pop(10);
        if (packet) {
            int ret = avcodec_send_packet(codec_ctx_, packet);
            av_packet_free(&packet);
            av_log(NULL, AV_LOG_VERBOSE, "DecodeThread::Run(): %d\n",ret);
            if (ret < 0) {
                av_strerror(ret, err2str, sizeof(err2str));
                av_log(NULL, AV_LOG_ERROR, "Failed to send packet: %s\n", err2str);
                break;
            }
            // 读解码后的数据
            while (true) {
                ret = avcodec_receive_frame(codec_ctx_, frame);
                if (ret == 0) {
                    frame_queue_->Push(frame);
                    continue;
                }
                if (AVERROR(EAGAIN) == ret) {
                    break;
                } else {
                    abort_ = 1;
                    av_strerror(ret, err2str, sizeof(err2str));
                    av_log(NULL, AV_LOG_ERROR, "Failed to receive frame: %s\n", err2str);
                    break;
                }
            }
        } else {
            av_log(NULL, AV_LOG_ERROR, "Failed to receive packet\n");
        }
    }
    av_log(NULL, AV_LOG_INFO, "DecodeThread::Stop()\n");
}
